﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WSSGServer{
   

    public struct Vector3
    {
        public float X;
        public float Y;
        public float Z;

        public Vector3(float x = 0, float y = 0, float z = 0)
        {
            X = x; Y = y; Z = z;
        }

        public override string ToString()
        {
            //return X + ";" + Y + ";" + Z + ";";
            return String.Format("{0:0.00};{1:0.00};{2:0.00}", X, Y, Z);
        }


        // возвращает нормализованный вектор
        public Vector3 normalized
        {
            get
            {
                return Vector3.Normalize(this);
            }
        }

        // возвращает длину вектора
        public float magnitude
        {
            get
            {
                return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
            }
        }

        // возвращает длину вектора в квадрате
        public float sqrMagnitude
        {
            get
            {
                return X * X + Y * Y + Z * Z;
            }
        }

        // возвращает нулевой вектор
        public static Vector3 zero
        {
            get
            {
                return new Vector3(0f, 0f, 0f);
            }
        }

        // возвращает единичный вектор
        public static Vector3 one
        {
            get
            {
                return new Vector3(1f, 1f, 1f);
            }
        }

        public static Vector3 forward
        {
            get
            {
                return new Vector3(0f, 0f, 1f);
            }
        }

        public static Vector3 back
        {
            get
            {
                return new Vector3(0f, 0f, -1f);
            }
        }

        public static Vector3 up
        {
            get
            {
                return new Vector3(0f, 1f, 0f);
            }
        }

        public static Vector3 down
        {
            get
            {
                return new Vector3(0f, -1f, 0f);
            }
        }
        public static Vector3 left
        {
            get
            {
                return new Vector3(-1f, 0f, 0f);
            }
        }

        public static Vector3 right
        {
            get
            {
                return new Vector3(1f, 0f, 0f);
            }
        }

        // оператор сложения векторов
        public static Vector3 operator +(Vector3 one, Vector3 other)
        {
            return new Vector3(one.X + other.X, one.Y + other.Y, one.Z + other.Z);
        }

        // унарный оператор отрицания
        public static Vector3 operator -(Vector3 v)
        {
            return new Vector3(-v.X, -v.Y, -v.Z);
        }

        // оператор вычитания
        public static Vector3 operator -(Vector3 one, Vector3 other)
        {
            return new Vector3(one.X - other.X, one.Y - other.Y, one.Z - other.Z);
        }

        // оператор умножения вектора на число
        public static Vector3 operator *(Vector3 a, float d)
        {
            return new Vector3(a.X * d, a.Y * d, a.Z * d);
        }

        // оператор умножения вектора на число
        public static Vector3 operator *(float d, Vector3 a)
        {
            return new Vector3(a.X * d, a.Y * d, a.Z * d);
        }

        // оператор деления вектора на число
        public static Vector3 operator /(Vector3 a, float d)
        {
            return new Vector3(a.X / d, a.Y / d, a.Z / d);
        }

        // оператор равенства векторов
        public static bool operator ==(Vector3 lhs, Vector3 rhs)
        {
            return SqrMagnitude(lhs - rhs) < 1E-9f;
        }

        // оператор неравенства векторов
        public static bool operator !=(Vector3 lhs, Vector3 rhs)
        {
            return SqrMagnitude(lhs - rhs) >= 1E-9f;
        }

        public override int GetHashCode()
        {
            return X.GetHashCode() ^ Y.GetHashCode() << 2 ^ Z.GetHashCode() >> 2;
        }

        public override bool Equals(object other)
        {
            if (!(other is Vector3))
            {
                return false;
            }
            return ((Vector3)other - this).sqrMagnitude < float.Epsilon;
            return this == (Vector3)other;
        }

        // функция нормализации вектора
        public static Vector3 Normalize(Vector3 value)
        {
            float num = Magnitude(value);
            if (num > 1E-05f)
            {
                return value / num;
            }
            return zero;
        }

        // функция нормализации текущего вектора
        public void Normalize()
        {
            float num = Magnitude(this);
            if (num > 1E-05f)
            {
                this /= num;
            }
            else
            {
                this = zero;
            }
        }

        // функция расчета расстояния между точками
        public static float Distance(Vector3 a, Vector3 b)
        {
            var vector = new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
            return (float)Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z);
        }

        // функция расчета длины вектора
        public static float Magnitude(Vector3 a)
        {
            return (float)Math.Sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z);
        }

        // функция расчета длины вектора в квадрате
        public static float SqrMagnitude(Vector3 a)
        {
            return a.X * a.X + a.Y * a.Y + a.Z * a.Z;
        }

        // линейная интерполяция векторов
        public static Vector3 Lerp(Vector3 from, Vector3 to, float t)
        {
            t = t > 1 ? 1 : t;
            t = t < 0 ? 0 : t;
            return new Vector3(from.X + (to.X - from.X) * t, from.Y + (to.Y - from.Y) * t, from.Z + (to.Z - from.Z) * t);
        }

        // масштабирование текущего вектора значениями другого вектора
        public void Scale(Vector3 scale)
        {
            X *= scale.X;
            Y *= scale.Y;
            Z *= scale.Z;
        }

        // векторное произведение векторов
        public static Vector3 Cross(Vector3 lhs, Vector3 rhs)
        {
            return new Vector3(lhs.Y * rhs.Z - lhs.Z * rhs.Y, lhs.Z * rhs.X - lhs.X * rhs.Z, lhs.X * rhs.Y - lhs.Y * rhs.X);
        }

        // функция вычисляет вектор отражения
        public static Vector3 Reflect(Vector3 inDirection, Vector3 inNormal)
        {
            return -2f * Dot(inNormal, inDirection) * inNormal + inDirection;
        }

        // скалярное произведение векторов
        public static float Dot(Vector3 lhs, Vector3 rhs)
        {
            return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z;
        }

        // угол между векторами
        public static float Angle(Vector3 from, Vector3 to)
        {
            var dot = Dot(from.normalized, to.normalized);
            dot = dot < -1 ? -1 : dot;
            dot = dot > 1 ? 1 : dot;
            return (float)Math.Acos(dot) * 57.29578f;
        }

        // возвращает вектор с минимальными значениями каждой составляющей двух векторов
        public static Vector3 Min(Vector3 lhs, Vector3 rhs)
        {
            return new Vector3(Math.Min(lhs.X, rhs.X), Math.Min(lhs.Y, rhs.Y), Math.Min(lhs.Z, rhs.Z));
        }

        // возвращает вектор с максимальными значениями каждой составляющей двух векторов
        public static Vector3 Max(Vector3 lhs, Vector3 rhs)
        {
            return new Vector3(Math.Max(lhs.X, rhs.X), Math.Max(lhs.Y, rhs.Y), Math.Max(lhs.Z, rhs.Z));
        }

        public bool Equals(Vector3 other)
        {
            return this == other;
        }


    }
}  